set(GC_DIR ../../gc)

set(COMMON_RUNTIME_SOURCES
    allocheap.cpp
    rhassert.cpp
    ${RUNTIME_DIR}/CachedInterfaceDispatch.cpp
    CachedInterfaceDispatch_Aot.cpp
    Crst.cpp
    DebugHeader.cpp
    MethodTable.cpp
    EHHelpers.cpp
    event.cpp
    FinalizerHelpers.cpp
    GcEnum.cpp
    GCHelpers.cpp
    gctoclreventsink.cpp
    gcheaputilities.cpp
    GCMemoryHelpers.cpp
    gcenv.ee.cpp
    GcStressControl.cpp
    HandleTableHelpers.cpp
    interoplibinterface_java.cpp
    MathHelpers.cpp
    MiscHelpers.cpp
    TypeManager.cpp
    ObjectLayout.cpp
    portable.cpp
    RestrictedCallouts.cpp
    RhConfig.cpp
    RuntimeInstance.cpp
    StackFrameIterator.cpp
    startup.cpp
    stressLog.cpp
    SyncClean.cpp
    thread.cpp
    threadstore.cpp
    UniversalTransitionHelpers.cpp
    yieldprocessornormalized.cpp

    ${GC_DIR}/gceventstatus.cpp
    ${GC_DIR}/gcbridge.cpp
    ${GC_DIR}/gcload.cpp
    ${GC_DIR}/gcconfig.cpp
    ${GC_DIR}/gchandletable.cpp
    ${GC_DIR}/gccommon.cpp
    ${GC_DIR}/gceewks.cpp
    ${GC_DIR}/gcwks.cpp
    ${GC_DIR}/gcscan.cpp
    ${GC_DIR}/handletable.cpp
    ${GC_DIR}/handletablecache.cpp
    ${GC_DIR}/handletablecore.cpp
    ${GC_DIR}/handletablescan.cpp
    ${GC_DIR}/objecthandle.cpp
    ${GC_DIR}/softwarewritewatch.cpp
    ${CLR_SRC_NATIVE_DIR}/minipal/xoshiro128pp.c
)

if (CLR_CMAKE_TARGET_UNIX AND NOT CLR_CMAKE_TARGET_ARCH_WASM)
    list(APPEND COMMON_RUNTIME_SOURCES
        ${RUNTIME_DIR}/asyncsafethreadmap.cpp
    )
endif()

set(SERVER_GC_SOURCES
    ${GC_DIR}/gceesvr.cpp
    ${GC_DIR}/gcsvr.cpp
)

set(STANDALONEGC_DISABLED_SOURCES
    clrgc.disabled.cpp
)

set(STANDALONEGC_ENABLED_SOURCES
    clrgc.enabled.cpp
)

set(FULL_RUNTIME_SOURCES
    AsmOffsetsVerify.cpp
    ThunksMapping.cpp
)

include_directories(inc)

include_directories(.)
include_directories(${GC_DIR})
include_directories(${GC_DIR}/env)
include_directories(${CMAKE_CURRENT_BINARY_DIR}/eventpipe/inc)
include_directories(${RUNTIME_DIR})

if (WIN32)
  set(GC_HEADERS
    ${GC_DIR}/env/common.h
    ${GC_DIR}/env/etmdummy.h
    ${GC_DIR}/env/gcenv.base.h
    ${GC_DIR}/env/gcenv.ee.h
    ${GC_DIR}/env/gcenv.h
    ${GC_DIR}/env/gcenv.interlocked.h
    ${GC_DIR}/env/gcenv.interlocked.inl
    ${GC_DIR}/env/gcenv.object.h
    ${GC_DIR}/env/gcenv.os.h
    ${GC_DIR}/env/gcenv.structs.h
    ${GC_DIR}/env/gcenv.sync.h
    ${GC_DIR}/env/gcenv.windows.inl
    ${GC_DIR}/env/volatile.h
    ${GC_DIR}/gc.h
    ${GC_DIR}/gcconfig.h
    ${GC_DIR}/gcdesc.h
    ${GC_DIR}/gcenv.ee.standalone.inl
    ${GC_DIR}/gcenv.inl
    ${GC_DIR}/gcevent_serializers.h
    ${GC_DIR}/gcevents.h
    ${GC_DIR}/gceventstatus.h
    ${GC_DIR}/gchandletableimpl.h
    ${GC_DIR}/gcimpl.h
    ${GC_DIR}/gcinterface.dac.h
    ${GC_DIR}/gcinterface.ee.h
    ${GC_DIR}/gcinterface.h
    ${GC_DIR}/gcpriv.h
    ${GC_DIR}/gcrecord.h
    ${GC_DIR}/gcscan.h
    ${GC_DIR}/handletable.h
    ${GC_DIR}/handletable.inl
    ${GC_DIR}/handletablepriv.h
    ${GC_DIR}/objecthandle.h
    ${GC_DIR}/softwarewritewatch.h)

  include_directories(windows)

  list(APPEND COMMON_RUNTIME_SOURCES
    windows/PalCommon.cpp
    windows/PalMinWin.cpp
    ${GC_DIR}/windows/gcenv.windows.cpp
  )

  list(APPEND FULL_RUNTIME_SOURCES windows/CoffNativeCodeManager.cpp)

  set(ASM_SUFFIX asm)
else()

  include_directories(unix)

  # sal.h, pshpack/poppack.h
  include_directories(../../pal/inc/rt)

  include(CheckIncludeFiles)
  include(CheckLibraryExists)

  include(${GC_DIR}/unix/configure.cmake)

  if(CLR_CMAKE_TARGET_ARCH_WASM)
    include_directories($ENV{EMSCRIPTEN/system/lib/libcxxabi/include})
  endif()

  # Disable building _Unwind_XXX style APIs of libunwind, since we don't use them.
  add_definitions(-D_LIBUNWIND_DISABLE_ZERO_COST_APIS=1)

  # Compile unwinding only for the current compilation target architecture
  add_definitions(-D_LIBUNWIND_IS_NATIVE_ONLY)

  if(CLR_CMAKE_TARGET_HAIKU)
    add_definitions(-DPT_GNU_EH_FRAME=PT_EH_FRAME)
  endif()

  list(APPEND COMMON_RUNTIME_SOURCES
    unix/PalUnix.cpp
    unix/PalCreateDump.cpp
    ${GC_DIR}/unix/gcenv.unix.cpp
    ${GC_DIR}/unix/numasupport.cpp
    ${GC_DIR}/unix/events.cpp
    ${GC_DIR}/unix/cgroup.cpp
  )

  list(APPEND FULL_RUNTIME_SOURCES
    unix/cgroupcpu.cpp
    unix/HardwareExceptions.cpp
    unix/NativeContext.cpp
    unix/UnixSignals.cpp
    unix/UnwindHelpers.cpp
    unix/UnixNativeCodeManager.cpp
  )

  include(${CLR_SRC_NATIVE_DIR}/external/llvm-libunwind.cmake)

  list(APPEND FULL_RUNTIME_SOURCES ${LLVM_LIBUNWIND_SOURCES})
  set(RUNTIME_SOURCES_ARCH_ASM ${LLVM_LIBUNWIND_ASM_SOURCES})

  set(ASM_SUFFIX S)
endif()

if (CLR_CMAKE_TARGET_APPLE)
  list(APPEND COMMON_RUNTIME_SOURCES
    interoplibinterface_objc.cpp
  )
endif (CLR_CMAKE_TARGET_APPLE)

if (CLR_CMAKE_TARGET_ARCH_AMD64)
  set(VXSORT_SOURCES
    ${GC_DIR}/vxsort/isa_detection.cpp
    ${GC_DIR}/vxsort/do_vxsort_avx2.cpp
    ${GC_DIR}/vxsort/do_vxsort_avx512.cpp
    ${GC_DIR}/vxsort/machine_traits.avx2.cpp
    ${GC_DIR}/vxsort/smallsort/bitonic_sort.AVX2.int64_t.generated.cpp
    ${GC_DIR}/vxsort/smallsort/bitonic_sort.AVX2.int32_t.generated.cpp
    ${GC_DIR}/vxsort/smallsort/bitonic_sort.AVX512.int64_t.generated.cpp
    ${GC_DIR}/vxsort/smallsort/bitonic_sort.AVX512.int32_t.generated.cpp
    ${GC_DIR}/vxsort/smallsort/avx2_load_mask_tables.cpp
  )
endif (CLR_CMAKE_TARGET_ARCH_AMD64)

if (CLR_CMAKE_TARGET_ARCH_ARM64)
set (VXSORT_SOURCES
    ${GC_DIR}/vxsort/isa_detection.cpp
    ${GC_DIR}/vxsort/do_vxsort_neon.cpp
    ${GC_DIR}/vxsort/machine_traits.neon.cpp
    ${GC_DIR}/vxsort/smallsort/bitonic_sort.NEON.uint32_t.generated.cpp
    ${GC_DIR}/vxsort/smallsort/bitonic_sort.scalar.uint64_t.generated.cpp
)
endif (CLR_CMAKE_TARGET_ARCH_ARM64)

if (CLR_CMAKE_TARGET_ARCH_ARM64 OR CLR_CMAKE_TARGET_ARCH_AMD64)
  set(DUMMY_VXSORT_SOURCES
    ${GC_DIR}/vxsort/dummy.cpp
  )
endif (CLR_CMAKE_TARGET_ARCH_ARM64 OR CLR_CMAKE_TARGET_ARCH_AMD64)

list(APPEND RUNTIME_SOURCES_ARCH_ASM
  ${RUNTIME_DIR}/${ARCH_SOURCES_DIR}/AllocFast.${ASM_SUFFIX}
  ${ARCH_SOURCES_DIR}/ExceptionHandling.${ASM_SUFFIX}
  ${ARCH_SOURCES_DIR}/GcProbe.${ASM_SUFFIX}
  ${ARCH_SOURCES_DIR}/MiscStubs.${ASM_SUFFIX}
  ${ARCH_SOURCES_DIR}/PInvoke.${ASM_SUFFIX}
  ${ARCH_SOURCES_DIR}/InteropThunksHelpers.${ASM_SUFFIX}
  ${RUNTIME_DIR}/${ARCH_SOURCES_DIR}/StubDispatch.${ASM_SUFFIX}
  ${ARCH_SOURCES_DIR}/UniversalTransition.${ASM_SUFFIX}
  ${RUNTIME_DIR}/${ARCH_SOURCES_DIR}/WriteBarriers.${ASM_SUFFIX}
)

if (CLR_CMAKE_TARGET_ARCH_AMD64 OR CLR_CMAKE_TARGET_ARCH_ARM64)
  list(APPEND RUNTIME_SOURCES_ARCH_ASM
    ${ARCH_SOURCES_DIR}/CachedInterfaceDispatchAot.${ASM_SUFFIX}
  )
endif ()

# Add architecture specific folder for looking up headers.
convert_to_absolute_path(ARCH_SOURCES_DIR ${ARCH_SOURCES_DIR})
include_directories(${ARCH_SOURCES_DIR})

if(NOT CLR_CMAKE_TARGET_ARCH_WASM)
  set(FEATURE_PERFTRACING 1)
  set(FEATURE_EVENT_TRACE 1)
endif()

if(FEATURE_PERFTRACING)
  add_definitions(-DFEATURE_PERFTRACING)
endif()

if(FEATURE_EVENT_TRACE)
  add_definitions(-DFEATURE_EVENT_TRACE)
endif()

if (NOT CLR_CMAKE_TARGET_ARCH_WASM)
  add_definitions(-DFEATURE_HIJACK)
endif()

add_definitions(-DFEATURE_BASICFREEZE)
add_definitions(-DFEATURE_CONSERVATIVE_GC)
if(CLR_CMAKE_TARGET_ARCH_AMD64 OR CLR_CMAKE_TARGET_ARCH_ARM64 OR CLR_CMAKE_TARGET_ARCH_RISCV64 OR CLR_CMAKE_TARGET_ARCH_LOONGARCH64)
  add_definitions(-DFEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP)
  add_definitions(-DFEATURE_MANUALLY_MANAGED_CARD_BUNDLES)
endif()
if(CLR_CMAKE_TARGET_ARCH_ARM OR CLR_CMAKE_TARGET_ARCH_WASM)
  add_definitions(-DFEATURE_64BIT_ALIGNMENT)
endif()

add_definitions(-DFEATURE_CUSTOM_IMPORTS)
add_definitions(-DFEATURE_DYNAMIC_CODE)
add_compile_definitions($<$<CONFIG:Debug,Checked>:FEATURE_GC_STRESS>)
add_definitions(-DFEATURE_NATIVEAOT)
add_definitions(-DVERIFY_HEAP)
add_definitions(-DNATIVEAOT)
add_definitions(-DFEATURE_CACHED_INTERFACE_DISPATCH)
if(CLR_CMAKE_TARGET_ARCH_I386 OR CLR_CMAKE_TARGET_ARCH_ARM)
  add_definitions(-DINTERFACE_DISPATCH_CACHE_HAS_CELL_BACKPOINTER)
endif()
add_definitions(-D_LIB)

# there is a problem with undefined symbols when this is set
# add_definitions(-DSTRESS_HEAP)

if(CLR_CMAKE_TARGET_WIN32)
  set(FEATURE_ETW 1)
  add_definitions(-DFEATURE_ETW)
  add_definitions(-DFEATURE_SUSPEND_REDIRECTION)
  if (CLR_CMAKE_TARGET_ARCH_AMD64 OR CLR_CMAKE_TARGET_ARCH_ARM64)
    add_definitions(-DFEATURE_SPECIAL_USER_MODE_APC)
  endif()
  if (CLR_CMAKE_TARGET_ARCH_I386)
    add_compile_options($<$<COMPILE_LANGUAGE:ASM_MASM>:/safeseh>)
  endif()
else()
  if(NOT CLR_CMAKE_TARGET_APPLE AND NOT CLR_CMAKE_TARGET_ARCH_WASM)
    add_definitions(-DFEATURE_READONLY_GS_COOKIE)
  endif()
  include(unix/configure.cmake)
  include_directories(${CMAKE_CURRENT_BINARY_DIR})
endif()

if (CLR_CMAKE_TARGET_UNIX)

  if (CLR_CMAKE_TARGET_ARCH_AMD64)
    add_definitions(-DUNIX_AMD64_ABI)
  elseif (CLR_CMAKE_TARGET_ARCH_ARM)
    add_definitions(-DUNIX_ARM_ABI)
  elseif (CLR_CMAKE_TARGET_ARCH_I386)
    add_definitions(-DUNIX_X86_ABI)
  endif()

endif(CLR_CMAKE_TARGET_UNIX)

set(NATIVEAOT_RUNTIME_DIR ${CMAKE_CURRENT_SOURCE_DIR})

list(APPEND COMMON_RUNTIME_SOURCES ${GC_HEADERS})

convert_to_absolute_path(COMMON_RUNTIME_SOURCES ${COMMON_RUNTIME_SOURCES})
convert_to_absolute_path(FULL_RUNTIME_SOURCES ${FULL_RUNTIME_SOURCES})
convert_to_absolute_path(SERVER_GC_SOURCES ${SERVER_GC_SOURCES})
convert_to_absolute_path(STANDALONEGC_DISABLED_SOURCES ${STANDALONEGC_DISABLED_SOURCES})
convert_to_absolute_path(STANDALONEGC_ENABLED_SOURCES ${STANDALONEGC_ENABLED_SOURCES})
convert_to_absolute_path(RUNTIME_SOURCES_ARCH_ASM ${RUNTIME_SOURCES_ARCH_ASM})
convert_to_absolute_path(VXSORT_SOURCES ${VXSORT_SOURCES})
convert_to_absolute_path(DUMMY_VXSORT_SOURCES ${DUMMY_VXSORT_SOURCES})

if(NOT CLR_CMAKE_TARGET_ARCH_WASM)
  add_subdirectory(Full)
else()
  add_subdirectory(Portable)
endif()

if(FEATURE_PERFTRACING)
  add_subdirectory(eventpipe)
endif()
